from pure_pagination import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render
from django.views.generic.base import View
from apps.courses.models import Course, CourseTag, CourseResource, Video
from apps.operations.models import UserFavorite, UserCourse, CourseComments
# 登录验证的继承类
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q


class VideoView(LoginRequiredMixin, View):
    login_url = "/login/"

    # 未登录时跳转到的页面
    # 登录后跳回来在userapp中的login视图中写
    def get(self, request, course_id, video_id, *args, **kwargs):
        """获取课程章节信息"""
        course = Course.objects.get(id=int(course_id))
        course.click_nums += 1
        course.save()

        video = Video.objects.get(id=int(video_id))

        # 查询用户是否已经关联了该课程
        user_courses = UserCourse.objects.filter(user=request.user, course=course)
        if not user_courses:
            # 未查询到关联信息，在表中创建关联信息
            user_course = UserCourse(user=request.user, course=course)
            user_course.save()
            course.students += 1
            course.save()

        # 该课的同学还学习过
        # 1. 学习过该课程的所有同学
        user_courses = UserCourse.objects.filter(course=course)
        # 2. 拿到所有该课程学习同学的id
        user_ids = [user_course.user.id for user_course in user_courses]
        # 3. 查询这些id的关联课程记录，并按课程的热度排序
        all_courses = UserCourse.objects.filter(user_id__in=user_ids).order_by("-course__click_nums")[:5]
        # 4. 通过课程关联表拿到相关课程对象
        # related_courses = [user_course.course for user_course in all_courses if user_course.course.id != course.id]
        related_courses = set()
        for item in all_courses:
            if item.course.id != course.id:
                related_courses.add(item.course)

        # 课程资源
        course_resouces = CourseResource.objects.filter(course=course)

        return render(request, "course-play.html", {
            "course": course,
            "course_resouces": course_resouces,
            "related_courses": related_courses,
            "video": video,
        })


class CourseCommentView(LoginRequiredMixin, View):
    login_url = "/login/"

    # 未登录时跳转到的页面
    # 登录后跳回来在userapp中的login视图中写
    def get(self, request, course_id, *args, **kwargs):
        """获取课程章节信息"""
        course = Course.objects.get(id=int(course_id))
        course.click_nums += 1
        course.save()

        comments = CourseComments.objects.filter(course=course)

        # 1. 用户和课程之间的关联
        # 2. 对view进行login登录的验证
        # 3. 其它课程

        # 查询用户是否已经关联了该课程
        user_courses = UserCourse.objects.filter(user=request.user, course=course)
        if not user_courses:
            # 未查询到关联信息，在表中创建关联信息
            user_course = UserCourse(user=request.user, course=course)
            user_course.save()
            course.students += 1
            course.save()

        # 该课的同学还学习过
        # 1. 学习过该课程的所有同学
        user_courses = UserCourse.objects.filter(course=course)
        # 2. 拿到所有该课程学习同学的id
        user_ids = [user_course.user.id for user_course in user_courses]
        # 3. 查询这些id的关联课程记录，并按课程的热度排序
        all_courses = UserCourse.objects.filter(user_id__in=user_ids).order_by("-course__click_nums")[:5]
        # 4. 通过课程关联表拿到相关课程对象，-course__click_nums外键属性
        # related_courses = [user_course.course for user_course in all_courses if user_course.course.id != course.id]
        related_courses = set()
        for item in all_courses:
            # 课程学生关联表的课程外键的id值进行筛选
            if item.course.id != course.id:
                related_courses.add(item.course)

        # 课程资源
        course_resouces = CourseResource.objects.filter(course=course)

        return render(request, "course-comment.html", {
            "course": course,
            "course_resouces": course_resouces,
            "related_courses": related_courses,
            "comments": comments,
        })


class CourseLessonView(LoginRequiredMixin, View):
    login_url = "/login/"

    # 未登录时跳转到的页面
    # 登录后跳回来在userapp中的login视图中写
    def get(self, request, course_id, *args, **kwargs):
        """获取课程章节信息"""
        course = Course.objects.get(id=int(course_id))
        course.click_nums += 1
        course.save()

        # 1. 用户和课程之间的关联
        # 2. 对view进行login登录的验证
        # 3. 其它课程

        # 查询用户是否已经关联了该课程
        user_courses = UserCourse.objects.filter(user=request.user, course=course)
        if not user_courses:
            # 未查询到关联信息，在表中创建关联信息
            user_course = UserCourse(user=request.user, course=course)
            user_course.save()
            course.students += 1
            course.save()

        # 该课的同学还学习过
        # 1. 学习过该课程的所有同学
        user_courses = UserCourse.objects.filter(course=course)
        # 2. 拿到所有该课程学习同学的id
        user_ids = [user_course.user.id for user_course in user_courses]
        # 3. 查询这些id的关联课程记录，并按课程的热度排序
        all_courses = UserCourse.objects.filter(user_id__in=user_ids).order_by("-course__click_nums")[:5]
        # 4. 通过课程关联表拿到相关课程对象
        # related_courses = [user_course.course for user_course in all_courses if user_course.course.id != course.id]
        related_courses = set()
        for item in all_courses:
            if item.course.id != course.id:
                related_courses.add(item.course)

        # 课程资源
        course_resouces = CourseResource.objects.filter(course=course)

        return render(request, "course-video.html", {
            "course": course,
            "course_resouces": course_resouces,
            "related_courses": related_courses,
        })


class CourseDetailView(View):
    def get(self, request, course_id, *args, **kwargs):
        """获取课程详情"""
        course = Course.objects.get(id=int(course_id))
        course.click_nums += 1
        course.save()

        # 获取机构和课程收藏状态
        has_fav_course = False
        has_fav_org = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course.id, fav_type=1):
                has_fav_course = True
            if UserFavorite.objects.filter(user=request.user, fav_id=course.course_org.id, fav_type=2):
                has_fav_org = True

        # 通过课程的tag字段做课程的推荐
        # tag = course.tag
        # related_courses = []
        # if tag:
        #     related_courses = Course.objects.filter(tag=tag).exclude(id=course_id)[:3]
        #     # 查找相同标签的课程，并去掉当前课程
        #     # 过滤一批数据exclude(id__in=[course_id]) 过滤单个数据exclude(id=course_id)
        # 通过课程的tag外键表做课程的推荐
        tags = course.coursetag_set.all()
        # 当前课程拥有的所有标签对象
        tag_list = [tag.tag for tag in tags]
        # 列表生成式将queryset中的对象的tag的value值取出来放到列表中
        course_tags = CourseTag.objects.filter(tag__in=tag_list).exclude(course__id=course.id)
        # 去除原本课程本身
        # course__id， 取外键的属性__(双下划线)
        # related_courses = [course_tag.course for course_tag in course_tags]
        # 如果原课程具有多个标签与其它单一课程重复，由于是用标签表生成对象则会生成多个相同对象(相同标签个数)，导致重复。
        # 解决方案利用集合自动去重
        related_courses = set()
        for course_tag in course_tags:
            related_courses.add(course_tag.course)

        students = course.usercourse_set.all()[:3]
        # 学过该课程的学生
        return render(request, "course-detail.html", {
            "course": course,
            "has_fav_course": has_fav_course,
            "has_fav_org": has_fav_org,
            "related_courses": related_courses,
            "students": students,
        })


class CourseListView(View):
    def get(self, request, *args, **kwargs):
        """获取课程列表信息"""
        # 默认排序，以时间最新为规则
        all_courses = Course.objects.order_by("-add_time")
        hot_courses = Course.objects.order_by("-click_nums")[:3]

        # 搜索关键词
        keywords = request.GET.get("keywords", "")
        s_type = "course"
        if keywords:
            all_courses = all_courses.filter(Q(name__icontains=keywords)
                                             | Q(desc__icontains=keywords) | Q(detail__icontains=keywords))
        # 课程排序
        sort = request.GET.get("sort", "")
        if sort == "students":
            all_courses = Course.objects.order_by("-students")
        elif sort == "hot":
            all_courses = Course.objects.order_by("-click_nums")
        # 对课程机构数据进行分页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1

        p = Paginator(all_courses, per_page=1, request=request)
        # 传入筛选后的查询集每页展示多少数据
        courses = p.page(page)
        # 页码包含的对象
        return render(request, "course-list.html", {
            "all_courses": courses,
            "sort": sort,
            "hot_courses": hot_courses,
            "s_type": s_type,
            "keywords": keywords,
        })
